/*
 * channelmonitor.c
 *
 * Created: 12/10/2012 12:17:26 PM
 *  Author: duerk@msoe.edu <Kevin Duer>
 *			zimmermane@msoe.edu <Evan Zimmerman>
 *			woottons@msoe.edu <Scott Wootton>
 *			
 * Purpose: to monitor the channel for 2400 bits/second
 */ 


#include <avr/io.h>
#include <stdbool.h>		//for boolean
#include "channelMonitor.h" //defines functions
#include <avr/io.h>			//i/o register definitions
#include <avr/interrupt.h>	//interrupt definitions
#include <stdint.h>			//for uint types
#include <stdlib.h>			//for rand
#include <stdbool.h>		//for boolean
#include "transmission.h"

volatile bool previousCol;

/* initChannelMonitor()
 * Purpose: To setup the channel monitor
 * Parameters: None
 * Returns: None
 */
void initChannelMonitor(){
	idle = false;						//Set all of the signals to be false
	collision = false;
	busy = false;
	transmitting = false;
	previousCol = false;
	
	MCUCR = (1<<ISC11)|(0<<ISC10);		//Begin listening for a (1=ISC11)&(0=ISC10) => Falling Edge
	GICR = (1<<INT1); 					//Enable INT1 interrupts
	fallingEdge = true;					//looking for a falling edge

	TCCR1A = 0x00;						//Set Timer0 to CTC Mode
	TCCR1B = (1<<WGM12)|T1_PRESCALER_CODE; 				//Sets up the Timer1 Prescaler, without it running
//	TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10)); //Prevents the Timer1 from counting
	TIMSK |= (1<<OCIE1A);				//Enable Timer1 OCR1A Interrupts
	OCR1A = T1_OVERFLOW;				//Sets up the overflow value
	DDRD |= (0<<PD6)|(0<<PD3);			//Sets the ICP1 to be an input
	//TCCR1B |= T1_PRESCALER_CODE; //Start Timer1 Counting
	sei();								//enable global interrupts
}

/* INT1_vect
 * Purpose: 
 * Parameters:
 * Returns:
 */
ISR(INT1_vect)
{
	TCNT1 = 0; //Reset TCNT0
	
	if(fallingEdge){
		//Start looking for rising edge
		fallingEdge = false;
		MCUCR = (1<<ISC11)|(1<<ISC10);		//(1=ISC11)&(1=ISC10)
	} else {
		//Start looking for a falling edge
		fallingEdge = true;
		MCUCR = (1<<ISC11)|(0<<ISC10);		//Falling Edge
	}
	//Current state is busy.  Idle and Collision states will be set in the timer
	// overflow
	busy = true;
	idle = false;
	collision = false;
}

/* TIMER1_COMPA_vect
 * Purpose: 
 * Parameters:
 * Returns:
 */
ISR(TIMER1_COMPA_vect){
//	PORTB = 0xFF;
	uint8_t val = (PIND>>PD6)&0x01;		//Shift PIND over to place ICP1 all the way to the right
										//and strip all of the other bits off
	TCNT1 = 0;//Reset TCNT0
	if(val==0x01)
	{
		//ICP1 = 1 (idle state)
		idle = true;					//Idle state
		collision = false;
		busy = false;
		if(previousCol)
		{
			handleIdle();
			previousCol = false;
		}			
	} else {
		//ICP1 = 0 (Collision detected)
		idle = false;
		collision = true;				//Collision state
		busy = false;
		if(transmitting)
		{
			handleCollision();
			previousCol = true;
		}
	}
}


